package util;

import org.apache.commons.codec.digest.DigestUtils;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.SAXReader;
import org.dom4j.io.XMLWriter;
import ws.schild.jave.EncoderException;
import ws.schild.jave.MultimediaInfo;
import ws.schild.jave.MultimediaObject;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.*;
import java.util.*;

/**
 * @author Europa
 * @create 2020-05-15 1:27
 */
public final class FileTools {

    private static final Map<String, List<String>> MD5_MAP = new HashMap<>(512);

    private static final Map<String, String> FILE_SIZE = new HashMap<>(1 << 28);

    private static long fileSize;

    public static int[] loadArray(String path, int size) {
        int[] array = new int[size];
        String filename = path + "/" + size + ".xml";
        File file = new File(filename);
        if (!file.exists()) {
            try {
                throw new FileNotFoundException("文件不存在: " + file.getAbsolutePath());
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            }
        }
        SAXReader saxReader = new SAXReader();
        try {
            Document document = saxReader.read(file);
            Element root = document.getRootElement();
            List<Element> list = root.elements();
            for (int i = 0; i < list.size(); i++) {
                Element element = list.get(i);
                String text = element.getText();
                array[i] = Integer.parseInt(text);
            }
        } catch (DocumentException e) {
            e.printStackTrace();
        }

        return array;
    }

    public static void createRandomNumber(String path, int size) {
        int[] array = new int[size];
        String filename = path + "/" + size + ".xml";
        File file = new File(filename);
        if (file.exists()) {
            boolean delete = file.delete();
            if (!delete) {
                System.err.println("文件删除失败: " + file.getAbsolutePath());
                return;
            }
        }
        // 创建文档对象
        Document doc = DocumentHelper.createDocument();
        // 创建根节点
        Element root = doc.addElement("list");
        Random random = new Random();
        // 向数组添加元素
        for (int i = 0; i < array.length; i++) {
            // 向根节点添加元素
            Element value = root.addElement("value");
            // 添加属性
            value.addAttribute("line", String.valueOf(i));
            // 生成随机数
            int r = random.nextInt(size);
            // 添加文本
            value.addText(String.valueOf(r));
        }
        FileOutputStream out = null;

        XMLWriter writer = null;
        try {
            out = new FileOutputStream(filename);
            // xml格式化,便于人眼阅读
            OutputFormat format = OutputFormat.createPrettyPrint();
            format.setEncoding("utf-8");
            writer = new XMLWriter(out, format);
            writer.write(doc);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (writer != null) {
                try {
                    writer.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            close(out);
        }
        System.out.println("创建成功");
    }

    public static void close(Closeable closeable) {
        if (closeable != null) {
            try {
                closeable.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 删除文件夹下的图片
     *
     * @param path 磁盘路径
     */
    public static void deleteImage(String path) {
        File file = new File(path);
        if (!file.exists()) {
            System.out.println("路径不存在");
            return;
        }
        File[] files = file.listFiles();
        if (files != null) {
            for (File f : files) {
                try {
                    BufferedImage image = ImageIO.read(f);
                    if (image != null) {
                        boolean delete = f.delete();
                        if (delete) {
                            System.out.println(f.getName() + "\t删除成功");
                        } else {
                            System.err.println(f.getName() + "\t删除失败");
                        }
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        } else {
            System.out.println("该路径下没有文件");
        }
    }

    /**
     * md5计算重复的文件
     *
     * @param path 文件夹路径
     * @return Map<String, List < String>>
     * {@code String md5值}
     * {@code List<String> 文件路径}
     */
    public static Map<String, List<String>> repetitiveFile(String path) {
        File file = new File(path);
        if (!file.exists()) {
            System.out.println("路径不存在");
            return null;
        }
        File[] files = file.listFiles();
        if (files != null) {
            for (File f : files) {
                if (f.isDirectory()) {
                    repetitiveFile(f.getAbsolutePath());
                } else {
                    String md5 = fileMd5(f.getAbsolutePath());
                    if (StringTools.notEmpty(md5)) {
                        ArrayList<String> list = new ArrayList<>();
                        list.add(f.getAbsolutePath());
                        List<String> put = MD5_MAP.put(md5, list);
                        if (put != null) {
                            put.add(f.getAbsolutePath());
                            MD5_MAP.put(md5, put);
                        }
                    }
                }
            }
        }
        return MD5_MAP;
    }

    public static String fileMd5(String path) {
        String md5Hex = null;
        try (FileInputStream stream = new FileInputStream(path)) {
            md5Hex = DigestUtils.md5Hex(stream);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return md5Hex;
    }

    public static void filesSize(String filepath) {
        File file = new File(filepath);
        if (!file.exists()) {
            System.out.println("文件不存在");
            return;
        }
        File[] files = file.listFiles();
        if (files == null) {
            return;
        }
        for (File f : files) {
            if (f.isDirectory()) {
                filesSize(f.getAbsolutePath());
            } else {
                fileSize += f.length();
            }
        }
    }

    public static long getFileSize() {
        return fileSize;
    }

    public static void delete0sizeFile(String filepath) {
        File file = new File(filepath);
        if (!file.exists()) {
            System.out.println("文件不存在");
            return;
        }
        File[] files = file.listFiles();
        if (files == null) {
            return;
        }
        if (files.length > 0) {
            for (File f : files) {
                if (f.isDirectory()) {
                    delete0sizeFile(f.getAbsolutePath());
                } else {
                    if (f.length() == 0) {
                        boolean delete = f.delete();
                        System.out.println(f.getAbsolutePath() + " 刪除 " + delete);
                    }
                }
            }
        } else {
            boolean delete = file.delete();
            System.out.println(file.getAbsolutePath() + " 刪除 " + delete);
        }
    }

    public static long videosTime(String path, int start, int end) {
        long time = 0L;
        File file = new File(path);
        if (!file.exists()) {
            return 0L;
        }
        File[] files = file.listFiles();
        if (files == null || files.length < 1) {
            return 0L;
        }
        if (end > files.length || start > end || start < 0) {
            System.out.println("start or end 错误");
            return 0L;
        }
        for (int i = start; i < end; i++) {
            try {
                MultimediaObject instance = new MultimediaObject(files[i]);
                MultimediaInfo result = instance.getInfo();
                time += result.getDuration() / 1000;
            } catch (EncoderException e) {
                e.printStackTrace();
            }
        }
        return time;
    }

}
